package org.agle4j.framework.utils;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 描述：FTP上传下载工具类
 * @author hyx
 * @version 1.0
 */
public class FtpUtil {
	private static final Logger LOG = LogManager.getLogger(FtpUtil.class);
	
	private static FTPClient ftp = new FTPClient();;
	private static final Properties FTP_PROPS = loadProps("sys.properties") ;
	
	private FtpUtil() {
	}
	
	/**
	 * 连接ftp服务器
	 * @throws IOException 
	 * @throws SocketException 
	 */
	private static void connect(String userName, String passworld) throws Exception {
		FTPClientConfig ftpClientConfig = new FTPClientConfig(FTPClientConfig.SYST_NT);
		ftp.configure(ftpClientConfig);
		
		ftp.connect(getString(FTP_PROPS, "sys.ftp.ip") , getInt(FTP_PROPS, "sys.ftp.port"));
		ftp.login(userName, passworld);		
	}

	/**
	 * 退出关闭连接
	 * @throws IOException 
	 */
	private static void close() throws IOException {
		if (ftp.isConnected()) {
			try {
				ftp.logout();
			} finally {
				ftp.disconnect();
			}
		}
	}

	/**
	 * 上传文件
	 * @param userName 用户名
	 * @param passworld 密码
	 * @param dest 上传到ftp的 路径+文件名
	 * @param is 要上传的流
	 * @return
	 * @throws Exception 
	 */
	public static boolean upload(String userName, String passworld, String dest, InputStream is) throws Exception {
		boolean flag = false;
		connect(userName,passworld);
		int reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			close();
			return flag;
		}
		try {
			String destFile = dest.replace("\\\\", "/");
			String destDir = destFile.substring(0, destFile.lastIndexOf("/"));

			FTPFile[] ftpFiles = ftp.listDirectories("\\");
			boolean isExist = false;
			for (FTPFile ftpFile : ftpFiles) {
				if (destDir.equals(ftpFile.toString())) {
					isExist = true;
					break;
				}
			}

			if (!isExist) {
				ftp.makeDirectory(destDir);
			}

			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			flag = ftp.storeFile(dest, is);
			if (flag) {
				LOG.debug("上传成功");
			} else {
				LOG.debug("上传失败");
			}
		}finally {
			IOUtils.closeQuietly(is);
			close();
		}
		return flag;
	}

	/**
	 * 下载文件
	 * @param userName 用户名
	 * @param passworld 密码
	 * @param filePath ftp中选择下载的 路径+文件名
	 * @return
	 * @throws Exception 
	 */
	public static InputStream download(String userName, String passworld,String filePath) throws Exception {
		InputStream is = null;
		connect(userName,passworld);
		int reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			close();
			return null;
		}
		try {
			is = ftp.retrieveFileStream(filePath);
			if (ftp.completePendingCommand()) {
				LOG.debug("下载流读取完成");
			}
		}finally {
			close();
		}
		return is;
	}

	/**
	 * 加载属性文件
	 */
	private static Properties loadProps(String fileName) {
		Properties props = null ;
		try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName) ){
			if(is == null) {
				throw new FileNotFoundException(fileName + " file is not found") ;
			}
			props = new Properties() ;
			props.load(is);
		} catch (IOException e) {
			LOG.error("load properties file failure", e);
		}
		return props;
	}
	
	/**
	 * 获取字符类属性(默认值为 空字符串)
	 */
	private static String getString(Properties props, String key) {
		return getString(props, key, "") ;
	}
	
	/**
	 * 获取字符型属性(可指定默认值)
	 */
	private static String getString(Properties props, String key, String defaultValue) {
		String value = defaultValue ;
		if(props.containsKey(key)) {
			value = props.getProperty(key) ;
		}
		return value ;
	}
	
	/**
	 * 获取数值类型属性(默认值为 0)
	 */
	private static int getInt(Properties props, String key) {
		return getInt(props, key, 0) ;
	}
	
	/**
	 * 获取数值类型属性(可指定默认值)
	 */
	private static int getInt(Properties props, String key, int defaultValue) {
		int value = defaultValue ;
		if(props.containsKey(key)) {
			value = Integer.valueOf(props.getProperty(key)) ;
		}
		return value ;
	}
	
}